package other.her.system.erp;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.api.annotations.RequestMethod;
import com.rkhd.platform.sdk.api.annotations.RestApi;
import com.rkhd.platform.sdk.api.annotations.RestMapping;
import com.rkhd.platform.sdk.api.annotations.RestQueryParam;
import com.rkhd.platform.sdk.creekflow.approvalevent.ApprovalEvent;
import com.rkhd.platform.sdk.creekflow.approvalevent.ApprovalEventRequest;
import com.rkhd.platform.sdk.creekflow.approvalevent.ApprovalEventResponse;
import com.rkhd.platform.sdk.data.model.Account;
import com.rkhd.platform.sdk.exception.ScriptBusinessException;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import com.rkhd.platform.sdk.model.XObject;
import com.rkhd.platform.sdk.service.XoqlService;
import com.rkhd.platform.sdk.trigger.DataResult;
import com.rkhd.platform.sdk.trigger.Trigger;
import com.rkhd.platform.sdk.trigger.TriggerRequest;
import com.rkhd.platform.sdk.trigger.TriggerResponse;
import org.apache.commons.lang.StringUtils;
import other.her.system.client.ErpUtils;
import other.her.system.utils.HCXObjectService;
import other.her.system.utils.ResultVo;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Description: 同步客户
 * @Author: 黎炎松
 * @Date: 2024/9/30 10:00
 */
@RestApi(baseUrl = "/her/account")
public class SyncAccount extends SyncSuper implements ApprovalEvent {
    private static final Logger LOGGER = LoggerFactory.getLogger();
    private static final String LOGGER_MSG = "推送客户数据到ERP ==> ";

    /**
     * 审批事件触发
     * @param request
     * @return
     * @throws ScriptBusinessException
     */
    @Override
    public ApprovalEventResponse execute(ApprovalEventRequest request) throws ScriptBusinessException {
        LOGGER.info(LOGGER_MSG + "审批事件触发开始 ");
        LOGGER.info("ObjectApiKey:" + request.getEntityApiKey() + " , DataId:" + request.getDataId());

        ApprovalEventResponse response = new ApprovalEventResponse();
        response.setSuccess(true);
        response.setMsg("success");
        pushAccountToErp(request.getDataId());
        return response;
    }

    /**
     * trigger 触发事件
     * @param request
     * @return
     * @throws ScriptBusinessException
     */
    //@Override
    //public TriggerResponse execute(TriggerRequest request) throws ScriptBusinessException {
    //    LOGGER.debug(LOGGER_MSG + "Trigger 触发开始 ");
    //    List<XObject> dataList = request.getDataList();
    //    List<DataResult> dataResultList = new ArrayList<>();
    //    for (XObject xObject : dataList) {
    //        dataResultList.add(new DataResult(true, "", xObject));
    //    }
    //    pushAccountToErp(dataList.get(0).getAttribute("id"));
    //    return new TriggerResponse(true, "处理完成", dataResultList);
    //}

    /**
     * 手动同步客户数据
     * @return
     */
    @RestMapping(value = "/pushToErp", method = RequestMethod.GET)
    public ResultVo pushToErp(@RestQueryParam(name = "accountId") Long accountId){
        LOGGER.info(LOGGER_MSG + "手动执行了推送: " + accountId);
        return pushAccountToErp(accountId);
    }

    public static void main(String[] args) {
        SyncAccount syncAccount = new SyncAccount();
        //syncAccount.pushAccountToErp(3580583069309601L);
    }

    /**
     * 推送客户到ERP
     * @param accountId
     * @return
     */
    public ResultVo pushAccountToErp(Long accountId) {
        try {
            LOGGER.info(LOGGER_MSG + "开始处理: " + accountId);
            // 获取客户信息
            String sql = "select id,ERPID__c,accountName,FNumber__c,ERPkeHu__c,FShortName__c,FContact__c,phone,DeliveryAddress__c,fax,fState,fCity,FPayCondition__c,shoukTj__c,ERPjieSuan__c,FBank__c,FAccount__c,FTaxNum__c," +
                    "FValueAddRate__c,currencyUnit,FIsCreditMgr__c,songHuodw__c,FTypeID__c,ownerId,ownerId.name as ownerName, zhangtao__c " +
                    "from account where id = " + accountId;
            List<JSONObject> records = XoqlService.instance().query(sql).getRecords();
            if (records.size() <= 0) {
                return ResultVo.error("获取客户信息异常");
            }
            JSONObject account = records.get(0);
            LOGGER.info(LOGGER_MSG + "account: " + account);

            // 获取所属的账套
            String zhangtao = getOptionStr(account.getJSONArray("zhangtao__c")); // 所属账套
            String fNumber = account.getString("FNumber__c"); // crm 客户编码 FNumber__c
            String erpNumber = account.getString("ERPkeHu__c"); // erp 客户编码 ERPkeHu__c
            String fItemID = account.getString("ERPID__c");// erpId 对应erp FItemID
            if (StringUtils.isBlank(zhangtao) || StringUtils.isBlank(fNumber)) {
                LOGGER.error(LOGGER_MSG + "客户所属账套、客户编码不可为空");
                return ResultVo.error("客户所属账套、客户编码不可为空");
            }

            // 如果 erpNumber 为空，取CRM的编码
            if (StringUtils.isBlank(erpNumber)) {
                erpNumber = fNumber;
            }

            Map<String, String> accountMap = accountList.stream().filter(v -> Objects.equals(v.get("accountName"), zhangtao)).findFirst().orElse(null);
            if (accountMap == null) {
                LOGGER.error(LOGGER_MSG + "所属账套获取异常");
                return ResultVo.error("所属账套获取异常");
            }

            // 获取推送的客户参数
            String accountName = account.getString("accountName"); // 客户名称
            String shortName = account.getString("FShortName__c"); // 客户简称
            String fState = getOptionStr(account.getJSONArray("fState")); // 省份
            String fCity = getOptionStr(account.getJSONArray("fCity")); // 市
            String bank = account.getString("FBank__c"); // 开户银行
            String bankNo = account.getString("FAccount__c"); // 银行卡号
            String taxNum = account.getString("FTaxNum__c"); // 税务登记号
            double rate = account.getDouble("FValueAddRate__c") * 100; // 税率
            String isCreditManage = account.getString("FIsCreditMgr__c"); // 是否进行信用管理  (erp: 1:是  0：否)
            String songHuodw = account.getString("songHuodw__c"); // 送货单位

            // 收款条件
            String domain = accountMap.get("domain");
            String payCondition = getOptionStr(account.getJSONArray("FPayCondition__c"));
            int payConditionId = getErpModeldId(payCondition, "FID", "t_PayColCondition", domain);

            // 结算方式
            //String shoukTj = getOptionStr(account.getJSONArray("shoukTj__c"));
            String shoukTj = account.getString("ERPjieSuan__c");
            int setId = getErpModeldId(shoukTj, "FItemID", "t_Settle", domain);

            // 币种
            String currencyUnit = getOptionStr(account.getJSONArray("currencyUnit"));
            int erpCurrencyId = getErpModeldId(currencyUnit, "FCurrencyID", "t_Currency", domain);

            // 客户分类
            String accountType = getOptionStr(account.getJSONArray("FTypeID__c"));
            int accountTypeId = getErpModeldId(accountType, "FInterID", "t_SubMessage", domain);

            // 所属业务员
            String ownerName = account.getString("ownerName");
            int ownerId = getErpModeldId(ownerName, "FItemID", "t_Base_Emp", domain);

            // 获取联系人数据
            String address = account.getString("DeliveryAddress__c"); // 地址
            String contactName = account.getString("FContact__c"); // 联系人
            String phone = account.getString("phone"); // 联系人电话
            String fax = account.getString("fax") != null ? account.getString("fax") : ""; // 传真

            // 推送到ERP 判断是新增还是修改
            int isAdd = 0;
            if (StringUtils.isBlank(fItemID)) {
                isAdd = 1;

                // 获取ERP最大的 FItemID
                fItemID = getErpId(domain);

                // 先判断crm是否有其他客户占用当前id,有占用把占用的值清空
                sql = String.format("select id from account where ERPID__c = '%s' and id != %s", fItemID, accountId);
                Account upAccount = HCXObjectService.queryOne(sql);
                if (upAccount != null) {
                    upAccount.setERPID__c(null);
                    HCXObjectService.update(upAccount);
                }
            } else {
                // 考虑ERP已经删除的情况
                String erpSql = String.format("select FNumber,FItemID from t_Item where FItemID = '%s' and FItemClassID = 1", fItemID);
                JSONObject erpAccount = ErpUtils.queryOne(erpSql, domain);

                // 判断 erpId 是否存在，不存在重新获取
                if (erpAccount == null) {
                    isAdd = 1;
                    fItemID = getErpId(domain);
                }
            }
            LOGGER.info(LOGGER_MSG + "isAdd: " + (isAdd == 1 ? "执行新增操作" : "执行更新操作"));
            LOGGER.info(LOGGER_MSG + "FItemID: " + fItemID);

            String syncErrStr = null;
            if (isAdd == 1) {

                // 1. 插入ERP t_Item 基础数据表
                String itemSql = "insert into t_Item (FItemID,FItemClassID,FExternID,FNumber,FParentID,FLevel,FDetail,FName,FUnUsed,FBrNo,FFullNumber,FDiff,FDeleted,FShortNumber,FFullName,UUID) " +
                        " values (%s,1,-1,'%s',0,1,1,'%s',0,0,'%s',0,0,'%s','%s',NEWID())";
                itemSql = String.format(itemSql, fItemID, erpNumber, accountName, accountName, erpNumber, accountName);
                ResultVo resultVo = ErpUtils.executeSql(itemSql, domain);
                if (resultVo.getCode() == 200) {

                    // 2. 插入ERP t_Organization 客户表 FStatus 固定为 1072
                    String orgSql = "insert into t_Organization (FItemID,FName,FShortName,FProvince,FCity,FAddress,FContact,FPhone,FFax,FPayCondition," +
                            "FSetID,FBank,FAccount,FTaxNum,FValueAddRate,FcurrencyID,FIsCreditMgr,F_102,FTypeID,Femployee,FStatus,FNumber)" +
                            " values (%s,'%s','%s','%s','%s','%s','%s','%s','%s',%s,%s,'%s','%s','%s',%s,%s,%s,'%s',%s,%s,%s,'%s')";
                    orgSql = String.format(orgSql, fItemID, accountName, shortName, fState, fCity, address, contactName, phone, fax, payConditionId, setId, bank,
                            bankNo, taxNum, rate, erpCurrencyId, isCreditManage, songHuodw, accountTypeId, ownerId, "1072", erpNumber);
                    resultVo = ErpUtils.executeSql(orgSql, domain);
                    if (resultVo.getCode() == 200) {

                        // 3. 插入 t_BaseProperty 基础表
                        String baseSql = String.format("insert into t_BaseProperty (FTypeID, FItemID, FCreateDate) values (3, %s, GETDATE())", fItemID);
                        ErpUtils.executeSql(baseSql, domain);

                    } else {
                        LOGGER.error(LOGGER_MSG + "插入 t_Organization 表异常:" + resultVo.getMsg());
                        syncErrStr = resultVo.getMsg();
                    }

                } else {
                    LOGGER.error(LOGGER_MSG + "插入 t_Item 表异常:" + resultVo.getMsg());
                    syncErrStr = resultVo.getMsg();
                }
            } else {
                // 修改 t_Item 表
                String upSql = "update t_Item set FName = '%s',FFullNumber = '%s',FFullName = '%s',FNumber = '%s',FShortNumber = '%s'  where FItemID = %s";
                upSql = String.format(upSql, accountName, accountName, accountName, erpNumber, erpNumber, fItemID);
                ErpUtils.executeSql(upSql, domain);

                // 修改 t_Organization 表
                upSql = "update t_Organization set FName = '%s',FShortName = '%s',FProvince = '%s',FCity = '%s',FAddress = '%s',FContact = '%s'," +
                        "FPhone = '%s',FFax = '%s',FPayCondition = %s,FSetID = %s,FBank = '%s',FAccount = '%s',FTaxNum = '%s',FValueAddRate = %s,FcurrencyID = %s,FIsCreditMgr = %s," +
                        "F_102 = '%s',FTypeID = %s,Femployee = %s,FNumber = '%s' where FItemID = %s ";
                upSql = String.format(upSql, accountName, shortName, fState, fCity, address, contactName, phone, fax, payConditionId, setId, bank, bankNo, taxNum, rate, erpCurrencyId,
                        isCreditManage, songHuodw, accountTypeId, ownerId, erpNumber, fItemID);
                ErpUtils.executeSql(upSql, domain);
            }
            LOGGER.info(LOGGER_MSG + "syncErrStr: " + syncErrStr);

            // 更新客户同步状态、以及ERPID
            Account upAccount = new Account();
            upAccount.setId(accountId);
            upAccount.setERPID__c(fItemID);
            upAccount.setSyncStatus__c(1);
            upAccount.setERPkeHu__c(erpNumber);
            upAccount.setFailureReasons__c(syncErrStr);
            if (StringUtils.isNotBlank(syncErrStr)) {
                // 同步失败
                upAccount.setSyncStatus__c(3);
                upAccount.setERPID__c(null);

                // 需要删除ERP中的数据
                String delSql = "delete from t_Item where FItemID = " + fItemID;
                ErpUtils.executeSql(delSql, domain);
            }
            HCXObjectService.update(upAccount);

            // 返回处理异常
            if (StringUtils.isNotBlank(syncErrStr)) {
                LOGGER.error(LOGGER_MSG + "处理异常");
                return ResultVo.error(syncErrStr);
            }

            LOGGER.info(LOGGER_MSG + "推送成功");
            return ResultVo.success(isAdd == 1 ? "新增客户成功" : "修改客户成功");
        } catch (Exception e) {
            e.printStackTrace();
            return ResultVo.error("推送异常: " + e.getMessage());
        }
    }

    /**
     * 获取ERP最大的 FItemID
     * @param domain
     * @return
     */
    public String getErpId(String domain) {
        String erpSql = "select max(FItemID) + 1 as FItemID from t_Item";
        return ErpUtils.queryOne(erpSql, domain).getString("FItemID");
    }

    /**
     * 获取erp模块对应的id值
     * @param fname
     * @param idKey
     * @param tableName
     * @param domain
     * @return
     */
    public Integer getErpModeldId(String fname, String idKey, String tableName, String domain) {
        int moduleId = 0;
        if (StringUtils.isNotBlank(fname)) {
            String erpSql = String.format("select %s from %s where FName = '%s'", idKey, tableName, fname);
            if (tableName.equals("t_SubMessage")) {
                erpSql += " and FTypeID = 501 ";
            }
            JSONObject obj = ErpUtils.queryOne(erpSql, domain);
            if (obj != null) {
                moduleId = obj.getInteger(idKey);
            }
        }
        return moduleId;
    }

    /**
     * 获取选项的字符串值
     * @param optionArr
     * @return
     */
    public String getOptionStr(JSONArray optionArr) {
        String optStr = "";
        if (optionArr != null && optionArr.size() > 0) {
            optStr = optionArr.stream().map(v -> v.toString()).collect(Collectors.joining(","));
        }
        return optStr;
    }



}
